#include "tcpserver.h"
#include "tcpconnection.h"

using namespace tiny_muduo;

TcpServer::TcpServer(EventLoop* loop, const Address& address)
    :loop_(loop),
    threadpool_(std::make_unique<EventLoopThreadPool>(loop_)),
    acceptor_(std::make_unique<Acceptor>(loop, address))
{
    acceptor_->SetNewConnectionCallback(std::bind(&TcpServer::HandleNewConnection, this, std::placeholders::_1));
}

TcpServer::~TcpServer()
{
    for(auto& pair : connections_)
    {
        TcpConnectionPtr ptr(pair.second);
        pair.second.reset();
        ptr->loop()->RunOneFunc(std::bind(&TcpConnection::ConnectionDestructor, ptr));
    }
}

// 关闭连接
void TcpServer::HandleClose(const TcpConnectionPtr& ptr)
{
    // @TODO 这里有问题，可以用ptr的loop执行。
    loop_->QueueOneFunc(std::bind(&TcpServer::HandleCloseInLoop, this, ptr));
}

void TcpServer::HandleCloseInLoop(const TcpConnectionPtr& ptr)
{
    assert(connections_.find(ptr->fd()) != connections_.end());

    connections_.erase(connections_.find(ptr->fd()));
    EventLoop* loop = ptr->loop();
    loop->QueueOneFunc(std::bind(&TcpConnection::ConnectionDestructor, ptr));
}

void TcpServer::HandleNewConnection(int connfd)
{
    EventLoop* loop = threadpool_->NextLoop();
    // printf("%s: TcpServer 新的连接 线程ID: %ld 管理\n", __FUNCTION__, loop->DebugShowTid());

    TcpConnectionPtr ptr = std::make_shared<TcpConnection>(loop, connfd);
    connections_[connfd] = ptr;
    ptr->SetConnectionCallback(connection_callback_);
    ptr->SetMessageCallback(message_callback_);
    ptr->SetCloseCallback(std::bind(&TcpServer::HandleClose, this, std::placeholders::_1));
    loop->RunOneFunc(std::bind(&TcpConnection::ConnectionEstablished, ptr));
}
